#!/usr/ruuci11/people/ruu/bin/perl -w

# analyse aqua .nrv files (.nrc files ?)
# usage "analaqua name.nrv name.nrc num_viol"
#

open (NRV, $ARGV[0]) || die "Can't open $ARGV[0]:$!";
# open (NRC, $ARGV[1]) || die "Can't open $ARGV[1]:$!";

$nviol = $ARGV[2];

while (<NRV>) {
  if (/^\$ DATA /) {
    $t = (split)[2];
    &distrib($t);  # distrib decides if we need the next section
    }		   # if it does it calls a sub, otherwise reads untill $ end
  }
  

sub distrib  {	

local ($t) = @_;
if ($t eq "RESTRAINT_VIOLATIONS") {
  &restr_viol;
  &anal_viol;
  }
else {
  do {$t = <NRV>;} until ($t =~ /^\$ END/);
  }
}


sub restr_viol {	# inlezen restr. violations

$t = <NRV>;
($nrestr,$nstruc) = (split (/\s/,$t))[3,5];
$nstruc -= 9;		# 9 kolommen met gegevens 
$t = <NRV>; 		# een lijn met hoofdingen, niet nodig
$t=0;
while (<NRV>) {
  last if (/^\$ END/);
  $fld[$t]=$_;
  $t++;  
  }
}

sub anal_viol {		# analyse viol
			# zoals in Camel pp 249 - 250
local (@datakeys,@t,$t,$k);
for ($t=1; $t<= $nstruc;$t++) {
  print "\nStructure $t\n";
  foreach (@fld) {
    push (@datakeys, (split(/\s+/))[$t+8]);
    }
  sub bydatakeys {$datakeys[$a] <=> $datakeys[$b];}
  @fld = @fld[sort bydatakeys 0..$#fld];
  print "\nLower bound violations\n--------------------\n";
  for ($k=0;$k<=$nviol-1;$k++) {
    @t = (split (/\s+/,$fld[$k]))[0..5,$t+8];
    print "$t[0] $t[1]  $t[2]\t\t$t[3] $t[4]  $t[5]\t$t[6]\n";
    }
  print "Upper bound violations\n----------------------\n";
  for ($k=$#fld;$k>=($#fld-$nviol);$k--) {
    @t = (split (/\s+/,$fld[$k]))[0..5,$t+8];
    print "$t[0] $t[1]  $t[2]\t\t$t[3] $t[4]  $t[5]\t$t[6]\n";
    }  
  $tel=0;$std=0.0;$tot=0;$top=$#fld; 	 # stat over restr (moet in functie)
  @t=();
  do {
     ($res)=(split(/\s+/,$fld[$top]))[$t+8];
#     $res = abs($res);
if ($res<0) {$res = -$res;}
     $tot+=$res; $t[$tel]=$res;$tel++;$top--;
     }
     until ($res ==0);$tel--;  # $tel is het aantal viol $#tel is 1 minder
  $avg=$tot/$tel;
  for ($k=0;$k<$tel;$k++) {
     $std +=($t[$k]-$avg)**2; }
  $te=$std;		# nodig voor algemene std.
  $std = sqrt ($std/($tel-1));
  printf("\nTotal UPPER BOUND violation: %.2f\n",$tot);
  printf("Number of violated restr:%5d, Average viol: %.2f +/- %.2f\n",
	$tel,$avg,$std);
  $std= sqrt ($te/($nrestr-1));
  printf("Number of restraints : %d, Average viol: %.2f +/- %.2f\n\n",
	$nrestr,$tot/$nrestr,$std);
  $tel=0;$std=0.0;$tot=0;
  @t=();
  do {
     ($res)=(split(/\s+/,$fld[$tel]))[$t+8];
#     $res = abs($res);
if ($res<0) {$res = -$res;}
     $tot+=$res; $t[$tel]=$res;$tel++;
     }
     until ($res ==0);$tel--;  # $tel is het aantal viol $#tel is 1 minder
  $avg=$tot/$tel;
  for ($k=0;$k<$tel;$k++) {
     $std +=($t[$k]-$avg)**2; }
  $te=$std;		# nodig voor algemene std.
  $std = sqrt ($std/($tel-1));
  printf("\nTotal LOWER BOUND violation: %.2f\n",$tot);
  printf("Number of violated restr:%5d, Average viol: %.2f +/- %.2f\n",
	$tel,$avg,$std);
  $std= sqrt ($te/($nrestr-1));
  printf("Number of restraints : %d, Average viol: %.2f +/- %.2f\n\n",
	$nrestr,$tot/$nrestr,$std);
  @datakeys=();
  }
}
